# Our Setup, Import Libaries, Create our Imshow Function and Download our Images
import cv2
import numpy as np
from matplotlib import pyplot as plt
# Define our imshow function
def imshow(title = "Image", image = None, size = 10):
w, h = image.shape[0], image.shape[1]
aspect_ratio = w/h
plt.figure(figsize=(size * aspect_ratio,size))
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title(title)
plt.show()
Optical flow is the pattern of apparent motion of image objects between two consecutive frames caused by the movemement of object or camera. It is 2D vector field where each vector is a displacement vector showing the movement of points from first frame to second. Consider the image below (Image Courtesy: Wikipedia article on Optical Flow).
Optik oqim - bu ob'ekt yoki kameraning harakati natijasida hosil bo'lgan ikkita ketma-ket kadrlar orasidagi tasvir ob'ektlarining ko'rinadigan harakati. Bu 2D vektor maydoni bo'lib, har bir vektor nuqtalarning birinchi kadrdan ikkinchisiga harakatini ko'rsatadigan siljish vektoridir. Ya'ni kadrdan kadrga o'tganda o'sha pixel boshqa joyga siljiydi. Yani siljish vektorlariga qarab harakatlanish
![]()
It shows a ball moving in 5 consecutive frames. The arrow shows its displacement vector. Optical flow has many applications in areas like :
Optical flow works on several assumptions:
Learn more - https://learnopencv.com/optical-flow-in-opencv/
# Load video stream, short clip
#cap = cv2.VideoCapture('walking_short_clip.mp4')
cap = cv2.VideoCapture(0)
# Get the height and width of the frame (required to be an interger)
width = int(cap.get(3))
height = int(cap.get(4))
# Set parameters for ShiTomasi corner detection
feature_params = dict( maxCorners = 100,
qualityLevel = 0.3,
minDistance = 7,
blockSize = 7 )
# Set parameters for lucas kanade optical flow
lucas_kanade_params = dict( winSize = (15,15),
maxLevel = 2,
criteria = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03))
# Create some random colors for drawing purposes
color = np.random.randint(0,255,(100,3))
# Take first frame and find corners in it
ret, prev_frame = cap.read()
prev_gray = cv2.cvtColor(prev_frame, cv2.COLOR_BGR2GRAY)
# Birinchi framedagi cornerlarni topib olamiz.
prev_corners = cv2.goodFeaturesToTrack(prev_gray, mask = None, **feature_params)
# Create a mask image for drawing purposes
mask = np.zeros_like(prev_frame)
while True:
ret, frame = cap.read()
if ret == True:
frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# calculate optical flow
new_corners, status, errors = cv2.calcOpticalFlowPyrLK(prev_gray,
frame_gray,
prev_corners,
None,
**lucas_kanade_params)
# Select and store good points
good_new = new_corners[status==1]
good_old = prev_corners[status==1]
# Draw the tracks
for i,(new,old) in enumerate(zip(good_new, good_old)):
a, b = new.ravel()
c, d = old.ravel()
mask = cv2.line(mask, (int(a),int(b)),(int(c),int(d)), color[i].tolist(), 2)
frame = cv2.circle(frame, (int(a),int(b)), 5, color[i].tolist(),-1)
img = cv2.add(frame,mask)
# Show Optical Flow
imshow('Optical Flow - Lucas-Kanade',img)
cv2.imshow('Optical Flow - Lucas-Kanade',img)
# Now update the previous frame and previous points
prev_gray = frame_gray.copy()
prev_corners = good_new.reshape(-1,1,2)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
else:
break
cap.release()
cv2.destroyAllWindows()
--------------------------------------------------------------------------- KeyboardInterrupt Traceback (most recent call last) Input In [3], in <cell line: 36>() 60 img = cv2.add(frame,mask) 62 # Show Optical Flow ---> 63 imshow('Optical Flow - Lucas-Kanade',img) 64 cv2.imshow('Optical Flow - Lucas-Kanade',img) 65 # Now update the previous frame and previous points Input In [1], in imshow(title, image, size) 11 plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB)) 12 plt.title(title) ---> 13 plt.show() File ~\anaconda3\envs\data_science\lib\site-packages\matplotlib\pyplot.py:368, in show(*args, **kwargs) 324 """ 325 Display all open figures. 326 (...) 365 explicitly there. 366 """ 367 _warn_if_gui_out_of_main_thread() --> 368 return _backend_mod.show(*args, **kwargs) File ~\anaconda3\envs\data_science\lib\site-packages\matplotlib_inline\backend_inline.py:41, in show(close, block) 39 try: 40 for figure_manager in Gcf.get_all_fig_managers(): ---> 41 display( 42 figure_manager.canvas.figure, 43 metadata=_fetch_figure_metadata(figure_manager.canvas.figure) 44 ) 45 finally: 46 show._to_draw = [] File ~\anaconda3\envs\data_science\lib\site-packages\IPython\core\display_functions.py:298, in display(include, exclude, metadata, transient, display_id, raw, clear, *objs, **kwargs) 296 publish_display_data(data=obj, metadata=metadata, **kwargs) 297 else: --> 298 format_dict, md_dict = format(obj, include=include, exclude=exclude) 299 if not format_dict: 300 # nothing to display (e.g. _ipython_display_ took over) 301 continue File ~\anaconda3\envs\data_science\lib\site-packages\IPython\core\formatters.py:178, in DisplayFormatter.format(self, obj, include, exclude) 176 md = None 177 try: --> 178 data = formatter(obj) 179 except: 180 # FIXME: log the exception 181 raise File ~\anaconda3\envs\data_science\lib\site-packages\decorator.py:232, in decorate.<locals>.fun(*args, **kw) 230 if not kwsyntax: 231 args, kw = fix(args, kw, sig) --> 232 return caller(func, *(extras + args), **kw) File ~\anaconda3\envs\data_science\lib\site-packages\IPython\core\formatters.py:222, in catch_format_error(method, self, *args, **kwargs) 220 """show traceback on failed format call""" 221 try: --> 222 r = method(self, *args, **kwargs) 223 except NotImplementedError: 224 # don't warn on NotImplementedErrors 225 return self._check_return(None, args[0]) File ~\anaconda3\envs\data_science\lib\site-packages\IPython\core\formatters.py:339, in BaseFormatter.__call__(self, obj) 337 pass 338 else: --> 339 return printer(obj) 340 # Finally look for special method names 341 method = get_real_method(obj, self.print_method) File ~\anaconda3\envs\data_science\lib\site-packages\IPython\core\pylabtools.py:151, in print_figure(fig, fmt, bbox_inches, base64, **kwargs) 148 from matplotlib.backend_bases import FigureCanvasBase 149 FigureCanvasBase(fig) --> 151 fig.canvas.print_figure(bytes_io, **kw) 152 data = bytes_io.getvalue() 153 if fmt == 'svg': File ~\anaconda3\envs\data_science\lib\site-packages\matplotlib\backend_bases.py:2319, in FigureCanvasBase.print_figure(self, filename, dpi, facecolor, edgecolor, orientation, format, bbox_inches, pad_inches, bbox_extra_artists, backend, **kwargs) 2315 try: 2316 # _get_renderer may change the figure dpi (as vector formats 2317 # force the figure dpi to 72), so we need to set it again here. 2318 with cbook._setattr_cm(self.figure, dpi=dpi): -> 2319 result = print_method( 2320 filename, 2321 facecolor=facecolor, 2322 edgecolor=edgecolor, 2323 orientation=orientation, 2324 bbox_inches_restore=_bbox_inches_restore, 2325 **kwargs) 2326 finally: 2327 if bbox_inches and restore_bbox: File ~\anaconda3\envs\data_science\lib\site-packages\matplotlib\backend_bases.py:1648, in _check_savefig_extra_args.<locals>.wrapper(*args, **kwargs) 1640 _api.warn_deprecated( 1641 '3.3', name=name, removal='3.6', 1642 message='%(name)s() got unexpected keyword argument "' 1643 + arg + '" which is no longer supported as of ' 1644 '%(since)s and will become an error ' 1645 '%(removal)s') 1646 kwargs.pop(arg) -> 1648 return func(*args, **kwargs) File ~\anaconda3\envs\data_science\lib\site-packages\matplotlib\_api\deprecation.py:412, in delete_parameter.<locals>.wrapper(*inner_args, **inner_kwargs) 402 deprecation_addendum = ( 403 f"If any parameter follows {name!r}, they should be passed as " 404 f"keyword, not positionally.") 405 warn_deprecated( 406 since, 407 name=repr(name), (...) 410 else deprecation_addendum, 411 **kwargs) --> 412 return func(*inner_args, **inner_kwargs) File ~\anaconda3\envs\data_science\lib\site-packages\matplotlib\backends\backend_agg.py:540, in FigureCanvasAgg.print_png(self, filename_or_obj, metadata, pil_kwargs, *args) 490 @_check_savefig_extra_args 491 @_api.delete_parameter("3.5", "args") 492 def print_png(self, filename_or_obj, *args, 493 metadata=None, pil_kwargs=None): 494 """ 495 Write the figure to a PNG file. 496 (...) 538 *metadata*, including the default 'Software' key. 539 """ --> 540 FigureCanvasAgg.draw(self) 541 mpl.image.imsave( 542 filename_or_obj, self.buffer_rgba(), format="png", origin="upper", 543 dpi=self.figure.dpi, metadata=metadata, pil_kwargs=pil_kwargs) File ~\anaconda3\envs\data_science\lib\site-packages\matplotlib\backends\backend_agg.py:436, in FigureCanvasAgg.draw(self) 432 # Acquire a lock on the shared font cache. 433 with RendererAgg.lock, \ 434 (self.toolbar._wait_cursor_for_draw_cm() if self.toolbar 435 else nullcontext()): --> 436 self.figure.draw(self.renderer) 437 # A GUI class may be need to update a window using this draw, so 438 # don't forget to call the superclass. 439 super().draw() File ~\anaconda3\envs\data_science\lib\site-packages\matplotlib\artist.py:73, in _finalize_rasterization.<locals>.draw_wrapper(artist, renderer, *args, **kwargs) 71 @wraps(draw) 72 def draw_wrapper(artist, renderer, *args, **kwargs): ---> 73 result = draw(artist, renderer, *args, **kwargs) 74 if renderer._rasterizing: 75 renderer.stop_rasterizing() File ~\anaconda3\envs\data_science\lib\site-packages\matplotlib\artist.py:50, in allow_rasterization.<locals>.draw_wrapper(artist, renderer) 47 if artist.get_agg_filter() is not None: 48 renderer.start_filter() ---> 50 return draw(artist, renderer) 51 finally: 52 if artist.get_agg_filter() is not None: File ~\anaconda3\envs\data_science\lib\site-packages\matplotlib\figure.py:2810, in Figure.draw(self, renderer) 2807 # ValueError can occur when resizing a window. 2809 self.patch.draw(renderer) -> 2810 mimage._draw_list_compositing_images( 2811 renderer, self, artists, self.suppressComposite) 2813 for sfig in self.subfigs: 2814 sfig.draw(renderer) File ~\anaconda3\envs\data_science\lib\site-packages\matplotlib\image.py:132, in _draw_list_compositing_images(renderer, parent, artists, suppress_composite) 130 if not_composite or not has_images: 131 for a in artists: --> 132 a.draw(renderer) 133 else: 134 # Composite any adjacent images together 135 image_group = [] File ~\anaconda3\envs\data_science\lib\site-packages\matplotlib\artist.py:50, in allow_rasterization.<locals>.draw_wrapper(artist, renderer) 47 if artist.get_agg_filter() is not None: 48 renderer.start_filter() ---> 50 return draw(artist, renderer) 51 finally: 52 if artist.get_agg_filter() is not None: File ~\anaconda3\envs\data_science\lib\site-packages\matplotlib\axes\_base.py:3082, in _AxesBase.draw(self, renderer) 3079 a.draw(renderer) 3080 renderer.stop_rasterizing() -> 3082 mimage._draw_list_compositing_images( 3083 renderer, self, artists, self.figure.suppressComposite) 3085 renderer.close_group('axes') 3086 self.stale = False File ~\anaconda3\envs\data_science\lib\site-packages\matplotlib\image.py:132, in _draw_list_compositing_images(renderer, parent, artists, suppress_composite) 130 if not_composite or not has_images: 131 for a in artists: --> 132 a.draw(renderer) 133 else: 134 # Composite any adjacent images together 135 image_group = [] File ~\anaconda3\envs\data_science\lib\site-packages\matplotlib\artist.py:50, in allow_rasterization.<locals>.draw_wrapper(artist, renderer) 47 if artist.get_agg_filter() is not None: 48 renderer.start_filter() ---> 50 return draw(artist, renderer) 51 finally: 52 if artist.get_agg_filter() is not None: File ~\anaconda3\envs\data_science\lib\site-packages\matplotlib\image.py:646, in _ImageBase.draw(self, renderer, *args, **kwargs) 644 renderer.draw_image(gc, l, b, im, trans) 645 else: --> 646 im, l, b, trans = self.make_image( 647 renderer, renderer.get_image_magnification()) 648 if im is not None: 649 renderer.draw_image(gc, l, b, im) File ~\anaconda3\envs\data_science\lib\site-packages\matplotlib\image.py:956, in AxesImage.make_image(self, renderer, magnification, unsampled) 953 transformed_bbox = TransformedBbox(bbox, trans) 954 clip = ((self.get_clip_box() or self.axes.bbox) if self.get_clip_on() 955 else self.figure.bbox) --> 956 return self._make_image(self._A, bbox, transformed_bbox, clip, 957 magnification, unsampled=unsampled) File ~\anaconda3\envs\data_science\lib\site-packages\matplotlib\image.py:557, in _ImageBase._make_image(self, A, in_bbox, out_bbox, clip_bbox, magnification, unsampled, round_to_pixel_border) 554 alpha = self._get_scalar_alpha() 555 output_alpha = _resample( # resample alpha channel 556 self, A[..., 3], out_shape, t, alpha=alpha) --> 557 output = _resample( # resample rgb channels 558 self, _rgb_to_rgba(A[..., :3]), out_shape, t, alpha=alpha) 559 output[..., 3] = output_alpha # recombine rgb and alpha 561 # at this point output is either a 2D array of normed data 562 # (of int or float) 563 # or an RGBA array of re-sampled input File ~\anaconda3\envs\data_science\lib\site-packages\matplotlib\image.py:193, in _resample(image_obj, data, out_shape, transform, resample, alpha) 191 if resample is None: 192 resample = image_obj.get_resample() --> 193 _image.resample(data, out, transform, 194 _interpd_[interpolation], 195 resample, 196 alpha, 197 image_obj.get_filternorm(), 198 image_obj.get_filterrad()) 199 return out KeyboardInterrupt:
Lucas-Kanade method computes optical flow for a sparse feature set (in our example, corners detected using Shi-Tomasi algorithm). OpenCV provides another algorithm to find the dense optical flow. It computes the optical flow for all the points in the frame. It is based on Gunner Farneback’s algorithm which is explained in “Two-Frame Motion Estimation Based on Polynomial Expansion” by Gunner Farneback in 2003.
Below sample shows how to find the dense optical flow using above algorithm. We get a 2-channel array with optical flow vectors, (u,v). We find their magnitude and direction. We color code the result for better visualization.
# Load video stream, long clip
cap = cv2.VideoCapture(0)
# Get the height and width of the frame (required to be an interger)
width = int(cap.get(3))
height = int(cap.get(4))
# Get first frame
ret, first_frame = cap.read()
previous_gray = cv2.cvtColor(first_frame, cv2.COLOR_BGR2GRAY)
hsv = np.zeros_like(first_frame)
hsv[...,1] = 255 #1 indexdagi col barchasi oq ranga tenglanyapti.
while True:
# Read of video file
ret, frame2 = cap.read()
if ret == True:
next_ = cv2.cvtColor(frame2,cv2.COLOR_BGR2GRAY)
# Computes the dense optical flow using the Gunnar Farneback’s algorithm
flow = cv2.calcOpticalFlowFarneback(previous_gray, next_,
None, 0.5, 3, 15, 3, 5, 1.2, 0)
# use flow to calculate the magnitude (speed) and angle of motion
# use these values to calculate the color to reflect speed and angle
magnitude, angle = cv2.cartToPolar(flow[...,0], flow[...,1])
hsv[...,0] = angle * (180 / (np.pi/2))
hsv[...,2] = cv2.normalize(magnitude, None, 0, 255, cv2.NORM_MINMAX)
final = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)
# Show our demo of Dense Optical Flow
imshow('Dense Optical Flow', final)
cv2.imshow('Dense Optical Flow', final)
# Store current image as previous image
previous_gray = next_
if cv2.waitKey(1) & 0xFF == ord('q'):
break
else:
break
cap.release()
cv2.destroyAllWindows()
--------------------------------------------------------------------------- KeyboardInterrupt Traceback (most recent call last) Input In [2], in <cell line: 14>() 31 final = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR) 33 # Show our demo of Dense Optical Flow ---> 34 imshow('Dense Optical Flow', final) 35 cv2.imshow('Dense Optical Flow', final) 37 # Store current image as previous image Input In [1], in imshow(title, image, size) 11 plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB)) 12 plt.title(title) ---> 13 plt.show() File ~\anaconda3\envs\data_science\lib\site-packages\matplotlib\pyplot.py:368, in show(*args, **kwargs) 324 """ 325 Display all open figures. 326 (...) 365 explicitly there. 366 """ 367 _warn_if_gui_out_of_main_thread() --> 368 return _backend_mod.show(*args, **kwargs) File ~\anaconda3\envs\data_science\lib\site-packages\matplotlib_inline\backend_inline.py:41, in show(close, block) 39 try: 40 for figure_manager in Gcf.get_all_fig_managers(): ---> 41 display( 42 figure_manager.canvas.figure, 43 metadata=_fetch_figure_metadata(figure_manager.canvas.figure) 44 ) 45 finally: 46 show._to_draw = [] File ~\anaconda3\envs\data_science\lib\site-packages\IPython\core\display_functions.py:298, in display(include, exclude, metadata, transient, display_id, raw, clear, *objs, **kwargs) 296 publish_display_data(data=obj, metadata=metadata, **kwargs) 297 else: --> 298 format_dict, md_dict = format(obj, include=include, exclude=exclude) 299 if not format_dict: 300 # nothing to display (e.g. _ipython_display_ took over) 301 continue File ~\anaconda3\envs\data_science\lib\site-packages\IPython\core\formatters.py:178, in DisplayFormatter.format(self, obj, include, exclude) 176 md = None 177 try: --> 178 data = formatter(obj) 179 except: 180 # FIXME: log the exception 181 raise File ~\anaconda3\envs\data_science\lib\site-packages\decorator.py:232, in decorate.<locals>.fun(*args, **kw) 230 if not kwsyntax: 231 args, kw = fix(args, kw, sig) --> 232 return caller(func, *(extras + args), **kw) File ~\anaconda3\envs\data_science\lib\site-packages\IPython\core\formatters.py:222, in catch_format_error(method, self, *args, **kwargs) 220 """show traceback on failed format call""" 221 try: --> 222 r = method(self, *args, **kwargs) 223 except NotImplementedError: 224 # don't warn on NotImplementedErrors 225 return self._check_return(None, args[0]) File ~\anaconda3\envs\data_science\lib\site-packages\IPython\core\formatters.py:339, in BaseFormatter.__call__(self, obj) 337 pass 338 else: --> 339 return printer(obj) 340 # Finally look for special method names 341 method = get_real_method(obj, self.print_method) File ~\anaconda3\envs\data_science\lib\site-packages\IPython\core\pylabtools.py:151, in print_figure(fig, fmt, bbox_inches, base64, **kwargs) 148 from matplotlib.backend_bases import FigureCanvasBase 149 FigureCanvasBase(fig) --> 151 fig.canvas.print_figure(bytes_io, **kw) 152 data = bytes_io.getvalue() 153 if fmt == 'svg': File ~\anaconda3\envs\data_science\lib\site-packages\matplotlib\backend_bases.py:2319, in FigureCanvasBase.print_figure(self, filename, dpi, facecolor, edgecolor, orientation, format, bbox_inches, pad_inches, bbox_extra_artists, backend, **kwargs) 2315 try: 2316 # _get_renderer may change the figure dpi (as vector formats 2317 # force the figure dpi to 72), so we need to set it again here. 2318 with cbook._setattr_cm(self.figure, dpi=dpi): -> 2319 result = print_method( 2320 filename, 2321 facecolor=facecolor, 2322 edgecolor=edgecolor, 2323 orientation=orientation, 2324 bbox_inches_restore=_bbox_inches_restore, 2325 **kwargs) 2326 finally: 2327 if bbox_inches and restore_bbox: File ~\anaconda3\envs\data_science\lib\site-packages\matplotlib\backend_bases.py:1648, in _check_savefig_extra_args.<locals>.wrapper(*args, **kwargs) 1640 _api.warn_deprecated( 1641 '3.3', name=name, removal='3.6', 1642 message='%(name)s() got unexpected keyword argument "' 1643 + arg + '" which is no longer supported as of ' 1644 '%(since)s and will become an error ' 1645 '%(removal)s') 1646 kwargs.pop(arg) -> 1648 return func(*args, **kwargs) File ~\anaconda3\envs\data_science\lib\site-packages\matplotlib\_api\deprecation.py:412, in delete_parameter.<locals>.wrapper(*inner_args, **inner_kwargs) 402 deprecation_addendum = ( 403 f"If any parameter follows {name!r}, they should be passed as " 404 f"keyword, not positionally.") 405 warn_deprecated( 406 since, 407 name=repr(name), (...) 410 else deprecation_addendum, 411 **kwargs) --> 412 return func(*inner_args, **inner_kwargs) File ~\anaconda3\envs\data_science\lib\site-packages\matplotlib\backends\backend_agg.py:541, in FigureCanvasAgg.print_png(self, filename_or_obj, metadata, pil_kwargs, *args) 494 """ 495 Write the figure to a PNG file. 496 (...) 538 *metadata*, including the default 'Software' key. 539 """ 540 FigureCanvasAgg.draw(self) --> 541 mpl.image.imsave( 542 filename_or_obj, self.buffer_rgba(), format="png", origin="upper", 543 dpi=self.figure.dpi, metadata=metadata, pil_kwargs=pil_kwargs) File ~\anaconda3\envs\data_science\lib\site-packages\matplotlib\image.py:1675, in imsave(fname, arr, vmin, vmax, cmap, format, origin, dpi, metadata, pil_kwargs) 1673 pil_kwargs.setdefault("format", format) 1674 pil_kwargs.setdefault("dpi", (dpi, dpi)) -> 1675 image.save(fname, **pil_kwargs) File ~\anaconda3\envs\data_science\lib\site-packages\PIL\Image.py:2300, in Image.save(self, fp, format, **params) 2297 fp = builtins.open(filename, "w+b") 2299 try: -> 2300 save_handler(self, fp, filename) 2301 except Exception: 2302 if open_fp: File ~\anaconda3\envs\data_science\lib\site-packages\PIL\PngImagePlugin.py:1374, in _save(im, fp, filename, chunk, save_all) 1372 _write_multiple_frames(im, fp, chunk, rawmode) 1373 else: -> 1374 ImageFile._save(im, _idat(fp, chunk), [("zip", (0, 0) + im.size, 0, rawmode)]) 1376 if info: 1377 for info_chunk in info.chunks: File ~\anaconda3\envs\data_science\lib\site-packages\PIL\ImageFile.py:518, in _save(im, fp, tile, bufsize) 515 if exc: 516 # compress to Python file-compatible object 517 while True: --> 518 l, s, d = encoder.encode(bufsize) 519 fp.write(d) 520 if s: KeyboardInterrupt: